home *** CD-ROM | disk | FTP | other *** search
/ Workbench Add-On / Workbench Add-On - Volume 1.iso / BBS-Archive / Comm / term-source.lha / Extras / Source / term-Source.lha / termTextBuffer.c < prev    next >
C/C++ Source or Header  |  1995-06-17  |  45KB  |  2,013 lines

  1. /*
  2. **    termTextBuffer.c
  3. **
  4. **    Support routines for the text buffer.
  5. **
  6. **    Copyright © 1990-1995 by Olaf `Olsen' Barthel
  7. **        All Rights Reserved
  8. */
  9.  
  10. #include "termGlobal.h"
  11.  
  12.     /* Gadget ID codes. */
  13.  
  14. enum    {    GAD_SCROLLER,GAD_UP,GAD_DOWN };
  15.  
  16.     /* Menu ID codes. */
  17.  
  18. enum    {    MEN_SEARCH,MEN_REPEAT,MEN_GOTO,MEN_CLEARBUF_CONTENTS,MEN_QUITBUF };
  19.  
  20.     /* Gadget ID codes. */
  21.  
  22. enum    {    GAD_STRING,GAD_LOAD,GAD_OK,GAD_CANCEL };
  23.  
  24.     /* A handy macro to determine the length of a string. */
  25.  
  26. #define LINE_WIDTH(s)    (s)[-1]
  27.  
  28.     /* The dimensions of the scroller images. */
  29.  
  30. #define ARROW_WIDTH    18
  31. #define ARROW_HEIGHT    11
  32.  
  33. STATIC struct NewMenu BufferMenu[] =
  34. {
  35.     { NM_TITLE, NULL,         0 , 0, 0, (APTR)0},
  36.     {  NM_ITEM, NULL,         0 , 0, 0, (APTR)MEN_SEARCH},
  37.     {  NM_ITEM, NULL,         0 , 0, 0, (APTR)MEN_REPEAT},
  38.     {  NM_ITEM, NM_BARLABEL,     0 , 0, 0, (APTR)0},
  39.     {  NM_ITEM, NULL,         0 , 0, 0, (APTR)MEN_GOTO},
  40.     {  NM_ITEM, NM_BARLABEL,     0 , 0, 0, (APTR)0},
  41.     {  NM_ITEM, NULL,         0 , 0, 0, (APTR)MEN_CLEARBUF_CONTENTS},
  42.     {  NM_ITEM, NM_BARLABEL,     0 , 0, 0, (APTR)0},
  43.     {  NM_ITEM, NULL,         0 , 0, 0, (APTR)MEN_QUITBUF},
  44.  
  45.     { NM_END, 0,             0 , 0, 0, (APTR)0}
  46. };
  47.  
  48.     /* Some private data (render info & window). */
  49.  
  50. STATIC struct Window        *BufferWindow;
  51. STATIC struct Screen        *BufferScreen;
  52. STATIC struct Menu        *BufferMenuStrip;
  53.  
  54. STATIC BYTE             BufferSignal;
  55.  
  56. STATIC struct RastPort        *BPort;
  57. STATIC APTR             BufferVisualInfo;
  58.  
  59. STATIC LONG             NumBufferLines,
  60.                  NumBufferColumns,
  61.                  LastTopLine;
  62.  
  63. STATIC struct DrawInfo        *BufferDrawInfo;
  64. STATIC struct Image        *BufferAmigaGlyph,
  65.                 *BufferCheckGlyph;
  66.  
  67. STATIC BYTE             BufferTerminated;
  68.  
  69. STATIC WORD             LocalTextFontWidth,
  70.                  LocalTextFontHeight,
  71.                  LocalTextFontBase;
  72.  
  73. STATIC struct TTextAttr         LocalTextFont;
  74. STATIC UBYTE __far         LocalTextFontName[MAX_FILENAME_LENGTH];
  75.  
  76. STATIC struct TTextAttr         LocalUserFont;
  77. STATIC UBYTE __far         LocalUserFontName[MAX_FILENAME_LENGTH];
  78.  
  79. STATIC LONG             TopLine = -1,
  80.                  DisplayedLines;
  81.  
  82. STATIC BYTE             SearchForward        = TRUE,
  83.                  IgnoreCase        = TRUE,
  84.                  WholeWords        = FALSE,
  85.                  NeedClipConversion    = FALSE;
  86.  
  87. STATIC struct Gadget        *Scroller,
  88.                 *UpArrow,
  89.                 *DownArrow;
  90.  
  91. STATIC struct Image        *UpImage,
  92.                 *DownImage;
  93.  
  94. STATIC UWORD            *BufferLineWidths,
  95.                 *BufferLineOffsets,
  96.                 *BufferColumnOffsets;
  97.  
  98. STATIC ULONG             ArrowWidth,
  99.                  ArrowHeight;
  100.  
  101.     /* DeleteScroller(VOID):
  102.      *
  103.      *    Delete scroller and arrow objects.
  104.      */
  105.  
  106. STATIC VOID
  107. DeleteScroller(VOID)
  108. {
  109.     if(Scroller)
  110.     {
  111.         DisposeObject(Scroller);
  112.  
  113.         Scroller = NULL;
  114.     }
  115.  
  116.     if(UpArrow)
  117.     {
  118.         DisposeObject(UpArrow);
  119.  
  120.         UpArrow = NULL;
  121.     }
  122.  
  123.     if(DownArrow)
  124.     {
  125.         DisposeObject(DownArrow);
  126.  
  127.         DownArrow = NULL;
  128.     }
  129.  
  130.     if(UpImage)
  131.     {
  132.         DisposeObject(UpImage);
  133.  
  134.         UpImage = NULL;
  135.     }
  136.  
  137.     if(DownImage)
  138.     {
  139.         DisposeObject(DownImage);
  140.  
  141.         DownImage = NULL;
  142.     }
  143. }
  144.  
  145.     /* CreateScroller(LONG Height):
  146.      *
  147.      *    Create scroller and arrow objects.
  148.      */
  149.  
  150. STATIC BYTE __regargs
  151. CreateScroller(LONG Height)
  152. {
  153.     struct DrawInfo    *DrawInfo;
  154.     BYTE         Result = FALSE;
  155.  
  156.     if(DrawInfo = GetScreenDrawInfo(BufferScreen))
  157.     {
  158.         if(UpImage = (struct Image *)NewObject(NULL,"sysiclass",
  159.             SYSIA_Size,    SYSISIZE_MEDRES,
  160.             SYSIA_Which,    UPIMAGE,
  161.             SYSIA_DrawInfo,    DrawInfo,
  162.         TAG_DONE))
  163.         {
  164.             if(DownImage = (struct Image *)NewObject(NULL,"sysiclass",
  165.                 SYSIA_Size,    SYSISIZE_MEDRES,
  166.                 SYSIA_Which,    DOWNIMAGE,
  167.                 SYSIA_DrawInfo,    DrawInfo,
  168.             TAG_DONE))
  169.             {
  170.                 LONG ScrollerHeight,LeftEdge;
  171.  
  172.                 ArrowWidth    = ARROW_WIDTH;
  173.                 ArrowHeight    = ARROW_HEIGHT;
  174.  
  175.                 GetAttr(IA_Height,    UpImage,&ArrowHeight);
  176.                 GetAttr(IA_Width,    UpImage,&ArrowWidth);
  177.  
  178.                 ScrollerHeight = Height - 2 * ArrowHeight;
  179.  
  180.                 LeftEdge = BufferScreen -> Width - ArrowWidth;
  181.  
  182.                 if(Scroller = NewObject(NULL,"propgclass",
  183.                     GA_ID,        GAD_SCROLLER,
  184.  
  185.                     GA_Top,        0,
  186.                     GA_Left,    LeftEdge,
  187.                     GA_Width,    ArrowWidth,
  188.                     GA_Height,    ScrollerHeight,
  189.                     GA_Immediate,    TRUE,
  190.                     GA_FollowMouse,    TRUE,
  191.                     GA_RelVerify,    TRUE,
  192.  
  193.                     PGA_Freedom,    FREEVERT,
  194.                     PGA_NewLook,    TRUE,
  195.  
  196.                     PGA_Visible,    1,
  197.                     PGA_Total,    1,
  198.                 TAG_DONE))
  199.                 {
  200.                     STATIC struct TagItem ArrowMappings[] = { GA_ID,GA_ID,TAG_END };
  201.  
  202.                     if(UpArrow = NewObject(NULL,"buttongclass",
  203.                         GA_ID,        GAD_UP,
  204.                         GA_Image,    UpImage,
  205.                         GA_Left,    LeftEdge,
  206.                         GA_Top,        ScrollerHeight,
  207.                         GA_Height,    ArrowHeight,
  208.                         GA_Width,    ArrowWidth,
  209.                         GA_Immediate,    TRUE,
  210.                         GA_RelVerify,    TRUE,
  211.                         GA_Previous,    Scroller,
  212.  
  213.                         ICA_TARGET,    ICTARGET_IDCMP,
  214.                         ICA_MAP,    ArrowMappings,
  215.                     TAG_DONE))
  216.                     {
  217.                         if(DownArrow = NewObject(NULL,"buttongclass",
  218.                             GA_ID,        GAD_DOWN,
  219.                             GA_Image,    DownImage,
  220.                             GA_Left,    LeftEdge,
  221.                             GA_Top,        ScrollerHeight + ArrowHeight,
  222.                             GA_Height,    ArrowHeight,
  223.                             GA_Width,    ArrowWidth,
  224.                             GA_Immediate,    TRUE,
  225.                             GA_RelVerify,    TRUE,
  226.                             GA_Previous,    UpArrow,
  227.  
  228.                             ICA_TARGET,    ICTARGET_IDCMP,
  229.                             ICA_MAP,    ArrowMappings,
  230.                         TAG_DONE))
  231.                             Result = TRUE;
  232.                     }
  233.                 }
  234.             }
  235.         }
  236.  
  237.         FreeScreenDrawInfo(BufferScreen,DrawInfo);
  238.     }
  239.  
  240.     if(!Result)
  241.         DeleteScroller();
  242.  
  243.     return(Result);
  244. }
  245.  
  246.     /* PrintLine(STRPTR Buffer,LONG LineNumber):
  247.      *
  248.      *    Print a line at a given line number in the displayed area.
  249.      */
  250.  
  251. STATIC VOID __regargs
  252. PrintLine(STRPTR Buffer,LONG LineNumber)
  253. {
  254.     WORD Length = Buffer[-1];
  255.  
  256.         /* Print the text. */
  257.  
  258.     if(Length)
  259.     {
  260.         Move(BPort,0,BufferLineOffsets[LineNumber] + LocalTextFontBase);
  261.  
  262.         if(Length > NumBufferColumns)
  263.             Length = NumBufferColumns;
  264.  
  265.         Text(BPort,Buffer,Length);
  266.     }
  267.  
  268.         /* The line doesn't exactly fill the displayed line,
  269.          * so erase the remaining columns.
  270.          */
  271.  
  272.     if(Length < BufferLineWidths[LineNumber])
  273.     {
  274.         SetAPen(BPort,0);
  275.         RectFill(BPort,BufferColumnOffsets[Length],BufferLineOffsets[LineNumber],BufferColumnOffsets[BufferLineWidths[LineNumber]] - 1,BufferLineOffsets[LineNumber + 1] - 1);
  276.         SetAPen(BPort,1);
  277.     }
  278.  
  279.     BufferLineWidths[LineNumber] = Length;
  280. }
  281.  
  282.     /* RedrawScreen(LONG FirstLine):
  283.      *
  284.      *    Redraw the contents of the entire screen and return the
  285.      *    number of lines actually drawn.
  286.      */
  287.  
  288. STATIC LONG __regargs
  289. RedrawScreen(LONG FirstLine)
  290. {
  291.     LONG i,Last,Line = 0,Result;
  292.  
  293.     ObtainSemaphore(BufferSemaphore);
  294.  
  295.         /* Determine last line to display. */
  296.  
  297.     if((Last = FirstLine + NumBufferLines) >= Lines)
  298.         Last = Lines;
  299.  
  300.     Result = Last - FirstLine;
  301.  
  302.     if(Lines)
  303.     {
  304.         if(LastTopLine != -1)
  305.         {
  306.             LONG Delta = FirstLine - LastTopLine;
  307.  
  308.             if(ABS(Delta) < NumBufferLines)
  309.             {
  310.                     /* No change? */
  311.  
  312.                 if(!Delta)
  313.                 {
  314.                     ReleaseSemaphore(BufferSemaphore);
  315.  
  316.                     return(Result);
  317.                 }
  318.                 else
  319.                 {
  320.                     LastTopLine = FirstLine;
  321.  
  322.                         /* Scrolled up? */
  323.  
  324.                     if(Delta < 0)
  325.                     {
  326.                         for(i = NumBufferLines - 1 ; i >= -Delta ; i--)
  327.                             BufferLineWidths[i] = BufferLineWidths[i + Delta];
  328.  
  329.                         ClipBlit(BPort,0,0,BPort,0,BufferLineOffsets[-Delta],BufferColumnOffsets[NumBufferColumns],BufferLineOffsets[NumBufferLines + Delta],MINTERM_COPY);
  330.  
  331.                         Last = FirstLine - Delta;
  332.                     }
  333.                     else
  334.                     {
  335.                         for(i = Delta ; i < NumBufferLines ; i++)
  336.                             BufferLineWidths[i - Delta] = BufferLineWidths[i];
  337.  
  338.                             /* Scrolled down. */
  339.  
  340.                         ClipBlit(BPort,0,BufferLineOffsets[Delta],BPort,0,0,BufferColumnOffsets[NumBufferColumns],BufferLineOffsets[NumBufferLines - Delta],MINTERM_COPY);
  341.  
  342.                         FirstLine += NumBufferLines - Delta;
  343.  
  344.                         Line = NumBufferLines - Delta;
  345.                     }
  346.                 }
  347.             }
  348.             else
  349.                 LastTopLine = FirstLine;
  350.         }
  351.         else
  352.             LastTopLine = FirstLine;
  353.  
  354.         if(BufferLines)
  355.         {
  356.             for(i = FirstLine ; i < Last ; i++)
  357.                 PrintLine(BufferLines[i],Line++);
  358.         }
  359.     }
  360.  
  361.     ReleaseSemaphore(BufferSemaphore);
  362.  
  363.         /* We didn't fill the whole screen, so clear the rest. */
  364.  
  365.     if(Result < NumBufferLines)
  366.     {
  367.         WORD i;
  368.  
  369.         for(i = Result ; i < NumBufferLines ; i++)
  370.             BufferLineWidths[i] = 0;
  371.  
  372.         SetAPen(BPort,0);
  373.         RectFill(BPort,0,BufferLineOffsets[Result],BufferColumnOffsets[NumBufferColumns] - 1,BufferLineOffsets[NumBufferLines] - 1);
  374.         SetAPen(BPort,1);
  375.     }
  376.  
  377.     return(Result);
  378. }
  379.  
  380.     /* MarkArea(LONG Column,LONG Line,LONG Length):
  381.      *
  382.      *    Mark an area in the term Buffer window.
  383.      */
  384.  
  385. STATIC VOID __regargs
  386. MarkArea(LONG Column,LONG Line,LONG Length)
  387. {
  388.     STATIC LONG OldColumn = -1,OldLine = -1,OldLength = -1;
  389.  
  390.     if(OldColumn != -1)
  391.         ClipBlit(BPort,0,0,BPort,BufferColumnOffsets[OldColumn],BufferLineOffsets[OldLine],BufferColumnOffsets[OldLength],LocalTextFontHeight,MINTERM_NOT_C);
  392.  
  393.     if(Column != -1)
  394.     {
  395.         if(OldColumn != Column || OldLine != Line || OldLength != Length)
  396.             ClipBlit(BPort,0,0,BPort,BufferColumnOffsets[Column],BufferLineOffsets[Line],BufferColumnOffsets[Length],LocalTextFontHeight,MINTERM_NOT_C);
  397.     }
  398.  
  399.     OldColumn    = Column;
  400.     OldLine        = Line;
  401.     OldLength    = Length;
  402. }
  403.  
  404.     /* BufferClipPage(struct BlockMarker *Marker):
  405.      *
  406.      *    Send the marked area to the clipboard.
  407.      */
  408.  
  409. STATIC VOID __inline
  410. BufferClipPage(struct BlockMarker *Marker)
  411. {
  412.     if(BufferLines)
  413.     {
  414.         struct IFFHandle *Handle;
  415.  
  416.         if(Handle = AllocIFF())
  417.         {
  418.             if(Handle -> iff_Stream = (ULONG)OpenClipboard(Config -> ClipConfig -> ClipboardUnit))
  419.             {
  420.                 InitIFFasClip(Handle);
  421.  
  422.                 if(!OpenIFF(Handle,IFFF_WRITE))
  423.                 {
  424.                     if(!PushChunk(Handle,ID_FTXT,ID_FORM,IFFSIZE_UNKNOWN))
  425.                     {
  426.                         if(!PushChunk(Handle,0,ID_CHRS,IFFSIZE_UNKNOWN))
  427.                         {
  428.                             LONG    Lines = Marker -> LastLine - Marker -> FirstLine - 1,
  429.                                 i;
  430.  
  431.                             if(LINE_WIDTH(BufferLines[Marker -> FirstLine]) > Marker -> FirstColumn)
  432.                                 WriteTrimmedString(Handle,&BufferLines[Marker -> FirstLine][Marker -> FirstColumn],LINE_WIDTH(BufferLines[Marker -> FirstLine]) - Marker -> FirstColumn,NeedClipConversion);
  433.  
  434.                             WriteChunkBytes(Handle,"\n",1);
  435.  
  436.                             if(Lines > 0)
  437.                             {
  438.                                 for(i = 0 ; i < Lines ; i++)
  439.                                 {
  440.                                     if(LINE_WIDTH(BufferLines[Marker -> FirstLine + 1 + i]))
  441.                                         WriteTrimmedString(Handle,BufferLines[Marker -> FirstLine + 1 + i],LINE_WIDTH(BufferLines[Marker -> FirstLine + 1 + i]),NeedClipConversion);
  442.  
  443.                                     WriteChunkBytes(Handle,"\n",1);
  444.                                 }
  445.                             }
  446.  
  447.                             if(Marker -> LastColumn > LINE_WIDTH(BufferLines[Marker -> LastLine]))
  448.                                 WriteTrimmedString(Handle,BufferLines[Marker -> LastLine],LINE_WIDTH(BufferLines[Marker -> LastLine]),NeedClipConversion);
  449.                             else
  450.                                 WriteTrimmedString(Handle,BufferLines[Marker -> LastLine],Marker -> LastColumn,NeedClipConversion);
  451.  
  452.                             WriteChunkBytes(Handle,"\n",1);
  453.  
  454.                             PopChunk(Handle);
  455.                         }
  456.  
  457.                         PopChunk(Handle);
  458.                     }
  459.  
  460.                     CloseIFF(Handle);
  461.                 }
  462.  
  463.                 CloseClipboard((struct ClipboardHandle *)Handle -> iff_Stream);
  464.             }
  465.  
  466.             FreeIFF(Handle);
  467.         }
  468.     }
  469. }
  470.  
  471.     /* BufferClip(VOID):
  472.      *
  473.      *    Start buffer marking process.
  474.      */
  475.  
  476. STATIC VOID
  477. BufferClip(VOID)
  478. {
  479.     struct BlockMarker    *Marker;
  480.     LONG             FirstX = BufferWindow -> MouseX / LocalTextFontWidth,
  481.                  FirstY = BufferWindow -> MouseY / LocalTextFontHeight;
  482.  
  483.     if(Marker = BM_SetMark(BufferWindow -> RPort,ToggleSelect,ToggleSelect,NumBufferColumns,NumBufferLines,0,0,TopLine,Lines,BufferWindow -> MouseX / LocalTextFontWidth,BufferWindow -> MouseY / LocalTextFontHeight,LocalTextFontWidth,LocalTextFontHeight))
  484.     {
  485.         struct IntuiMessage    *Massage;
  486.         ULONG             Code,IClass;
  487.         BYTE             Done = FALSE,Aborted = FALSE;
  488.         LONG             PlusX = LocalTextFontWidth - 1,
  489.                      MouseX,MouseY,
  490.                      Delta = 0;
  491.  
  492.         ReportMouse(TRUE,BufferWindow);
  493.  
  494.         while(!Done)
  495.         {
  496.             WaitPort(BufferWindow -> UserPort);
  497.  
  498.             while(Massage = (struct IntuiMessage *)GetMsg(BufferWindow -> UserPort))
  499.             {
  500.                 IClass    = Massage -> Class;
  501.                 Code    = Massage -> Code;
  502.                 MouseX    = Massage -> MouseX;
  503.                 MouseY    = Massage -> MouseY;
  504.  
  505.                 ReplyMsg(Massage);
  506.  
  507.                 if(IClass == IDCMP_INACTIVEWINDOW)
  508.                 {
  509.                     Done = Aborted = TRUE;
  510.  
  511.                     break;
  512.                 }
  513.  
  514.                 if(IClass == IDCMP_INTUITICKS && Delta != 0)
  515.                 {
  516.                     if(BufferLines)
  517.                     {
  518.                         if((Delta > 0 && TopLine + NumBufferLines < Lines) || (Delta < 0 && TopLine > 0))
  519.                         {
  520.                             if(Delta < 0)
  521.                             {
  522.                                 WORD i;
  523.  
  524.                                 for(i = NumBufferLines - 1 ; i > -Delta ; i--)
  525.                                     BufferLineWidths[i] = BufferLineWidths[i + Delta];
  526.  
  527.                                 if(DisplayedLines)
  528.                                     ClipBlit(BPort,0,0,BPort,0,LocalTextFontHeight,BufferColumnOffsets[NumBufferColumns],BufferLineOffsets[NumBufferLines - 1],MINTERM_COPY);
  529.  
  530.                                 BufferLineWidths[0] = NumBufferColumns;
  531.  
  532.                                 PrintLine(BufferLines[--TopLine],0);
  533.                             }
  534.                             else
  535.                             {
  536.                                 WORD i;
  537.  
  538.                                 for(i = Delta ; i < NumBufferLines ; i++)
  539.                                     BufferLineWidths[i - Delta] = BufferLineWidths[i];
  540.  
  541.                                 if(DisplayedLines)
  542.                                     ClipBlit(BPort,0,LocalTextFontHeight,BPort,0,0,BufferColumnOffsets[NumBufferColumns],BufferLineOffsets[NumBufferLines - 1],MINTERM_COPY);
  543.  
  544.                                 BufferLineWidths[NumBufferLines - 1] = NumBufferColumns;
  545.  
  546.                                 PrintLine(BufferLines[TopLine + NumBufferLines],NumBufferLines - 1);
  547.  
  548.                                 TopLine++;
  549.                             }
  550.  
  551.                             Marker -> Top += Delta;
  552.                             Marker -> LastY -= Delta;
  553.  
  554.                             BM_ExtendMark(Marker,(MouseX + PlusX) / LocalTextFontWidth,MouseY / LocalTextFontHeight,Delta);
  555.                         }
  556.                         else
  557.                             Delta = 0;
  558.                     }
  559.                 }
  560.  
  561.                 if(IClass == IDCMP_MOUSEBUTTONS && (Code & IECODE_UP_PREFIX))
  562.                 {
  563.                     BM_Draw(Marker,Marker -> Unselect);
  564.  
  565.                     Done = TRUE;
  566.  
  567.                     break;
  568.                 }
  569.  
  570.                 if(IClass == IDCMP_MOUSEMOVE)
  571.                 {
  572.                     BM_ExtendMark(Marker,(MouseX + PlusX) / LocalTextFontWidth,MouseY / LocalTextFontHeight,0);
  573.  
  574.                     if(MouseY < 1)
  575.                     {
  576.                         if(TopLine > 0)
  577.                             Delta = -1;
  578.                     }
  579.                     else
  580.                     {
  581.                         if(MouseY >= BufferWindow -> Height - 1 && TopLine + NumBufferLines < Lines)
  582.                             Delta = 1;
  583.                     }
  584.  
  585.                     while(Delta)
  586.                     {
  587.                         MouseX    = Window -> MouseX;
  588.                         MouseY    = Window -> MouseY;
  589.  
  590.                         if((Delta < 0 && MouseY > 0) || (Delta > 0 && MouseY < BufferWindow -> Height - 1))
  591.                             break;
  592.                         else
  593.                         {
  594.                             if(BufferLines)
  595.                             {
  596.                                 if((Delta > 0 && TopLine + NumBufferLines < Lines) || (Delta < 0 && TopLine > 0))
  597.                                 {
  598.                                     if(Delta < 0)
  599.                                     {
  600.                                         WORD i;
  601.  
  602.                                         for(i = NumBufferLines - 1 ; i > -Delta ; i--)
  603.                                             BufferLineWidths[i] = BufferLineWidths[i + Delta];
  604.  
  605.                                         if(DisplayedLines)
  606.                                             ClipBlit(BPort,0,0,BPort,0,LocalTextFontHeight,BufferColumnOffsets[NumBufferColumns],BufferLineOffsets[NumBufferLines - 1],MINTERM_COPY);
  607.  
  608.                                         BufferLineWidths[0] = NumBufferColumns;
  609.  
  610.                                         PrintLine(BufferLines[--TopLine],0);
  611.                                     }
  612.                                     else
  613.                                     {
  614.                                         WORD i;
  615.  
  616.                                         for(i = Delta ; i < NumBufferLines ; i++)
  617.                                             BufferLineWidths[i - Delta] = BufferLineWidths[i];
  618.  
  619.                                         if(DisplayedLines)
  620.                                             ClipBlit(BPort,0,LocalTextFontHeight,BPort,0,0,BufferColumnOffsets[NumBufferColumns],BufferLineOffsets[NumBufferLines - 1],MINTERM_COPY);
  621.  
  622.                                         BufferLineWidths[NumBufferLines - 1] = NumBufferColumns;
  623.  
  624.                                         PrintLine(BufferLines[TopLine + NumBufferLines],NumBufferLines - 1);
  625.  
  626.                                         TopLine++;
  627.                                     }
  628.  
  629.                                     Marker -> Top    += Delta;
  630.                                     Marker -> LastY    -= Delta;
  631.  
  632.                                     BM_ExtendMark(Marker,(MouseX + PlusX) / LocalTextFontWidth,MouseY / LocalTextFontHeight,Delta);
  633.  
  634.                                     SetGadgetAttrs(Scroller,BufferWindow,NULL,
  635.                                         PGA_Top,TopLine,
  636.                                     TAG_DONE);
  637.                                 }
  638.                                 else
  639.                                     break;
  640.                             }
  641.                             else
  642.                                 break;
  643.                         }
  644.                     }
  645.  
  646.                     Delta = 0;
  647.                 }
  648.             }
  649.         }
  650.  
  651.         ReportMouse(FALSE,BufferWindow);
  652.  
  653.         while(Massage = (struct IntuiMessage *)GetMsg(BufferWindow -> UserPort))
  654.             ReplyMsg(Massage);
  655.  
  656.         if(!Aborted)
  657.         {
  658.             if(FirstX != BufferWindow -> MouseX / LocalTextFontWidth || FirstY != BufferWindow -> MouseY / LocalTextFontHeight)
  659.             {
  660.                 SetWait(BufferWindow);
  661.  
  662.                 if(Marker -> FirstColumn == Marker -> Width)
  663.                 {
  664.                     Marker -> FirstLine++;
  665.  
  666.                     Marker -> FirstColumn = 0;
  667.                 }
  668.  
  669.                 if(Marker -> LastColumn == 0)
  670.                 {
  671.                     Marker -> LastLine--;
  672.  
  673.                     Marker -> LastColumn = Marker -> Width;
  674.                 }
  675.  
  676.                 if(Marker -> FirstLine <= Marker -> LastLine)
  677.                 {
  678.                     if(Marker -> FirstLine != Marker -> LastLine || Marker -> FirstColumn != Marker -> LastColumn)
  679.                     {
  680.                         if(BufferLines)
  681.                         {
  682.                             if(Marker -> FirstLine == Marker -> LastLine)
  683.                             {
  684.                                 if(NeedClipConversion)
  685.                                 {
  686.                                     UBYTE    Buffer[256];
  687.                                     LONG    Len,i;
  688.                                     STRPTR    Dest,
  689.                                         Source    = &BufferLines[Marker -> FirstLine][Marker -> FirstColumn];
  690.                                     LONG    Size    = Marker -> LastColumn - Marker -> FirstColumn;
  691.                                     UBYTE    c;
  692.  
  693.                                     BOOL    FirstWrite = TRUE;
  694.  
  695.                                     do
  696.                                     {
  697.                                         Len = MIN(Size,256);
  698.  
  699.                                         Size -= Len;
  700.  
  701.                                         for(i = 0, Dest = Buffer ; i < Len ; i++)
  702.                                         {
  703.                                             if(c = ISOConversion[*Source++])
  704.                                                 *Dest++ = c;
  705.                                             else
  706.                                                 *Dest++ = ' ';
  707.                                         }
  708.  
  709.                                         if(Dest > Buffer)
  710.                                         {
  711.                                             if(FirstWrite)
  712.                                             {
  713.                                                 FirstWrite = FALSE;
  714.  
  715.                                                 SaveClip(Buffer,(ULONG)Dest - (ULONG)&Buffer[0]);
  716.                                             }
  717.                                             else
  718.                                                 AddClip(Buffer,(ULONG)Dest - (ULONG)&Buffer[0]);
  719.                                         }
  720.                                     }
  721.                                     while(Size > 0);
  722.                                 }
  723.                                 else
  724.                                     SaveClip(&BufferLines[Marker -> FirstLine][Marker -> FirstColumn],Marker -> LastColumn - Marker -> FirstColumn);
  725.                             }
  726.                             else
  727.                                 BufferClipPage(Marker);
  728.                         }
  729.                     }
  730.                 }
  731.  
  732.                 ClrWait(BufferWindow);
  733.             }
  734.         }
  735.  
  736.         FreeVecPooled(Marker);
  737.     }
  738. }
  739.  
  740. STATIC VOID __regargs
  741. StartSearch(struct SearchInfo *SearchInfo,STRPTR SearchBuffer)
  742. {
  743.     LT_LockWindow(BufferWindow);
  744.  
  745.     if(Lines)
  746.     {
  747.         LONG LineNumber;
  748.  
  749.         ObtainSemaphore(BufferSemaphore);
  750.  
  751.         LineNumber = SearchTextBuffer(SearchInfo);
  752.  
  753.         ReleaseSemaphore(BufferSemaphore);
  754.  
  755.         if(LineNumber == -1)
  756.         {
  757.             MyEasyRequest(BufferWindow,LocaleString(MSG_TERMBUFFER_DID_NOT_FIND_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT),SearchBuffer);
  758.  
  759.             FlushMsg(BufferWindow);
  760.  
  761.             SearchInfo -> FoundY = -1;
  762.  
  763.             MarkArea(-1,-1,-1);
  764.         }
  765.         else
  766.         {
  767.             if(LineNumber < TopLine)
  768.             {
  769.                 MarkArea(-1,-1,-1);
  770.  
  771.                 DisplayedLines = RedrawScreen(TopLine = LineNumber);
  772.  
  773.                 SetGadgetAttrs(Scroller,BufferWindow,NULL,
  774.                     PGA_Top,TopLine,
  775.                 TAG_DONE);
  776.             }
  777.             else
  778.             {
  779.                 if(LineNumber > TopLine + DisplayedLines - 1)
  780.                 {
  781.                     MarkArea(-1,-1,-1);
  782.  
  783.                     if(LineNumber >= Lines - NumBufferLines)
  784.                     {
  785.                         LONG NewCurrentLine;
  786.  
  787.                         if((NewCurrentLine = Lines - NumBufferLines) < 0)
  788.                             NewCurrentLine = 0;
  789.  
  790.                         if(TopLine != NewCurrentLine)
  791.                             DisplayedLines = RedrawScreen(TopLine = NewCurrentLine);
  792.                     }
  793.                     else
  794.                         DisplayedLines = RedrawScreen(TopLine = LineNumber);
  795.  
  796.                     SetGadgetAttrs(Scroller,BufferWindow,NULL,
  797.                         PGA_Top,TopLine,
  798.                     TAG_DONE);
  799.                 }
  800.             }
  801.  
  802.             MarkArea(SearchInfo -> FoundX,LineNumber - TopLine,SearchInfo -> PatternWidth);
  803.         }
  804.     }
  805.     else
  806.         MyEasyRequest(BufferWindow,LocaleString(MSG_GLOBAL_NOTHING_IN_THE_BUFFER_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT));
  807.  
  808.     LT_UnlockWindow(BufferWindow);
  809. }
  810.  
  811. STATIC VOID __stdargs
  812. BufferDestructor(struct MsgItem *Item)
  813. {
  814.     Signal(BufferTask,1L << BufferSignal);
  815. }
  816.  
  817. STATIC BOOLEAN __regargs
  818. HandleBuffer(LONG TitleOffset)
  819. {
  820.     ULONG             LastSeconds    = 0,
  821.                  LastMicros    = 0,
  822.                  Seconds,
  823.                  Micros;
  824.     BOOLEAN             ClickAndActivate,
  825.                  UpdatePercent    = TRUE;
  826.  
  827.     ULONG             SignalSet;
  828.  
  829.     struct IntuiMessage    *Massage;
  830.     ULONG             MsgClass;
  831.     UWORD             MsgCode,MsgQualifier,LastQualifier = NULL;
  832.     WORD             MouseX,MouseY;
  833.  
  834.     UBYTE             Char,LastChar = 0;
  835.     LONG             LastWidth = 0;
  836.  
  837.     UBYTE             PercentBuffer[80];
  838.     UBYTE             SearchBuffer[256];
  839.  
  840.     struct TagItem        *TagList;
  841.  
  842.     STRPTR             PercentTemplate;
  843.  
  844.     BOOLEAN             RingBack = FALSE;
  845.  
  846.     struct SearchContext    *Context    = NULL;
  847.     struct SearchInfo    *SearchInfo    = NULL;
  848.  
  849.     struct Hook         HistoryHook;
  850.  
  851.     HistoryHook . h_Data = &TextBufferHistory;
  852.  
  853.     if(LocaleBase)
  854.         PercentTemplate = "%lD/%lD (%ld%%)";
  855.     else
  856.         PercentTemplate = "%ld/%ld (%ld%%)";
  857.  
  858.     do
  859.     {
  860.             /* Show where we are. */
  861.  
  862.         if(Lines && UpdatePercent)
  863.         {
  864.             LONG Width,Len;
  865.  
  866.             SetAPen(BufferScreen -> BarLayer -> rp,0);
  867.             SetBPen(BufferScreen -> BarLayer -> rp,1);
  868.             SetDrMd(BufferScreen -> BarLayer -> rp,JAM2);
  869.  
  870.             SPrintf(PercentBuffer,PercentTemplate,TopLine,Lines > NumBufferLines ? Lines - NumBufferLines : 0,(100 * (TopLine + DisplayedLines)) / Lines);
  871.  
  872.             Len = strlen(PercentBuffer);
  873.  
  874.             Move(BufferScreen -> BarLayer -> rp,TitleOffset,BufferScreen -> BarLayer -> rp -> Font -> tf_Baseline + 1);
  875.             Text(BufferScreen -> BarLayer -> rp,PercentBuffer,Len);
  876.  
  877.             Width = TextLength(BufferScreen -> BarLayer -> rp,PercentBuffer,Len);
  878.  
  879.             if(LastWidth > Width)
  880.             {
  881.                 SetAPen(BufferScreen -> BarLayer -> rp,1);
  882.  
  883.                 RectFill(BufferScreen -> BarLayer -> rp,TitleOffset + Width,1,TitleOffset + LastWidth - 1,BufferScreen -> BarLayer -> rp -> Font -> tf_YSize);
  884.             }
  885.  
  886.             LastWidth = Width;
  887.  
  888.             UpdatePercent = FALSE;
  889.         }
  890.  
  891.         SignalSet = Wait(SIG_KILL | SIG_TOFRONT | SIG_UPDATE | SIG_MOVEUP | PORTMASK(BufferWindow -> UserPort));
  892.  
  893.             /* Leave the town? */
  894.  
  895.         if(SignalSet & SIG_KILL)
  896.             BufferTerminated = RingBack = TRUE;
  897.  
  898.             /* Bring our window to the front. */
  899.  
  900.         if(SignalSet & SIG_TOFRONT)
  901.         {
  902.             if(Context)
  903.                 LT_ShowWindow(Context -> SearchHandle,TRUE);
  904.  
  905.             BumpWindow(BufferWindow);
  906.         }
  907.  
  908.             /* We've got one more line in the
  909.              * buffer.
  910.              */
  911.  
  912.         if(SignalSet & SIG_UPDATE)
  913.         {
  914.             if(BufferLines && Lines)
  915.             {
  916.                 if(Lines - TopLine > DisplayedLines && DisplayedLines < NumBufferLines)
  917.                 {
  918.                     LONG i = TopLine + DisplayedLines;
  919.  
  920.                     do
  921.                         PrintLine(BufferLines[i++],DisplayedLines++);
  922.                     while(DisplayedLines < NumBufferLines && i < Lines);
  923.                 }
  924.             }
  925.  
  926.             SetGadgetAttrs(Scroller,BufferWindow,NULL,
  927.                 PGA_Total,    Lines,
  928.                 PGA_Visible,    DisplayedLines,
  929.             TAG_DONE);
  930.  
  931.             UpdatePercent = TRUE;
  932.  
  933.             Signal(ThisProcess,SIG_HANDSHAKE);
  934.         }
  935.  
  936.             /* The contents of the buffer have moved
  937.              * up a line.
  938.              */
  939.  
  940.         if(SignalSet & SIG_MOVEUP)
  941.         {
  942.             if(TopLine > 0)
  943.             {
  944.                 LastTopLine = --TopLine;
  945.  
  946.                 SetGadgetAttrs(Scroller,BufferWindow,NULL,
  947.                     PGA_Top,TopLine,
  948.                 TAG_DONE);
  949.             }
  950.             else
  951.             {
  952.                 LONG i;
  953.  
  954.                 MarkArea(-1,-1,-1);
  955.  
  956.                 for(i = 0 ; i < NumBufferLines - 1 ; i++)
  957.                     BufferLineWidths[i] = BufferLineWidths[i + 1];
  958.  
  959.                 ClipBlit(BPort,0,BufferLineOffsets[1],BPort,0,0,BufferColumnOffsets[NumBufferColumns],BufferLineOffsets[NumBufferLines - 1],MINTERM_COPY);
  960.  
  961.                 PrintLine(BufferLines[NumBufferLines - 1],NumBufferLines - 1);
  962.             }
  963.  
  964.             UpdatePercent = TRUE;
  965.  
  966.             Signal(ThisProcess,SIG_HANDSHAKE);
  967.         }
  968.  
  969.             /* Process the incoming window
  970.              * input.
  971.              */
  972.  
  973.         while(Massage = (struct IntuiMessage *)GetMsg(BufferWindow -> UserPort))
  974.         {
  975.             if(Context && Context -> SearchWindow == Massage -> IDCMPWindow)
  976.             {
  977.                 MsgClass = NULL;
  978.  
  979.                 if(HandleSearchMessage(Context,&Massage))
  980.                 {
  981.                     BOOLEAN Ok = Context -> Ok;
  982.  
  983.                     DeleteSearchContext(Context);
  984.  
  985.                     Context = NULL;
  986.  
  987.                     if(Ok)
  988.                     {
  989.                         if(SearchInfo)
  990.                             DeleteSearchInfo(SearchInfo);
  991.  
  992.                         if(SearchInfo = CreateSearchInfo(SearchBuffer,SearchForward,IgnoreCase,WholeWords))
  993.                             StartSearch(SearchInfo,SearchBuffer);
  994.                     }
  995.                     else
  996.                     {
  997.                         if(SearchInfo)
  998.                             DeleteSearchInfo(SearchInfo);
  999.  
  1000.                         SearchInfo = NULL;
  1001.                     }
  1002.                 }
  1003.             }
  1004.             else
  1005.             {
  1006.                 MsgClass    = Massage -> Class;
  1007.                 MsgCode        = Massage -> Code;
  1008.                 MsgQualifier    = Massage -> Qualifier;
  1009.                 MouseX        = Massage -> MouseX;
  1010.                 MouseY        = Massage -> MouseY;
  1011.                 TagList        = (struct TagItem *)Massage -> IAddress;
  1012.                 Seconds        = Massage -> Seconds;
  1013.                 Micros        = Massage -> Micros;
  1014.  
  1015.                 ClickAndActivate = FALSE;
  1016.  
  1017.                 if(Seconds == LastSeconds && Micros == LastMicros)
  1018.                 {
  1019.                     if(Massage -> Class == IDCMP_ACTIVEWINDOW || Massage -> Class == IDCMP_MOUSEBUTTONS)
  1020.                         ClickAndActivate = TRUE;
  1021.                 }
  1022.  
  1023.                 LastSeconds    = Seconds;
  1024.                 LastMicros    = Micros;
  1025.  
  1026.                     /* This hack is necessary to obtain the
  1027.                      * character codes generated for the cursor
  1028.                      * keys. A control or alternate qualifier
  1029.                      * would spoil the result (i.e. we would
  1030.                      * not get a valid key code).
  1031.                      */
  1032.  
  1033.                 Massage -> Qualifier = NULL;
  1034.  
  1035.                 Char = KeyConvert(Massage,NULL,NULL);
  1036.  
  1037.                     /* Just in case anybody needs it... */
  1038.  
  1039.                 Massage -> Qualifier = MsgQualifier;
  1040.  
  1041.                 ReplyMsg((struct Message *)Massage);
  1042.             }
  1043.  
  1044.             if(MsgClass == IDCMP_ACTIVEWINDOW)
  1045.                 UpdatePercent = TRUE;
  1046.  
  1047.             if(MsgClass == IDCMP_IDCMPUPDATE)
  1048.             {
  1049.                 switch(GetTagData(GA_ID,0,TagList))
  1050.                 {
  1051.                     case GAD_UP:
  1052.  
  1053.                         if(TopLine > 0)
  1054.                         {
  1055.                             TopLine--;
  1056.  
  1057.                             MarkArea(-1,-1,-1);
  1058.  
  1059.                             SetGadgetAttrs(Scroller,BufferWindow,NULL,
  1060.                                 PGA_Top,TopLine,
  1061.                             TAG_DONE);
  1062.  
  1063.                             DisplayedLines = RedrawScreen(TopLine);
  1064.  
  1065.                             UpdatePercent = TRUE;
  1066.                         }
  1067.  
  1068.                         break;
  1069.  
  1070.                     case GAD_DOWN:
  1071.  
  1072.                         if(TopLine + NumBufferLines < Lines)
  1073.                         {
  1074.                             TopLine++;
  1075.  
  1076.                             MarkArea(-1,-1,-1);
  1077.  
  1078.                             SetGadgetAttrs(Scroller,BufferWindow,NULL,
  1079.                                 PGA_Top,TopLine,
  1080.                             TAG_DONE);
  1081.  
  1082.                             DisplayedLines = RedrawScreen(TopLine);
  1083.  
  1084.                             UpdatePercent = TRUE;
  1085.                         }
  1086.  
  1087.                         break;
  1088.                 }
  1089.             }
  1090.  
  1091.             if(MsgClass == IDCMP_MOUSEMOVE || MsgClass == IDCMP_GADGETDOWN || MsgClass == IDCMP_GADGETUP)
  1092.             {
  1093.                 LONG Position;
  1094.  
  1095.                 GetAttr(PGA_Top,Scroller,(ULONG *)&Position);
  1096.  
  1097.                 if(Position != TopLine)
  1098.                 {
  1099.                     MarkArea(-1,-1,-1);
  1100.  
  1101.                     DisplayedLines = RedrawScreen(TopLine = Position);
  1102.  
  1103.                     UpdatePercent = TRUE;
  1104.                 }
  1105.             }
  1106.  
  1107.             if(MsgClass == IDCMP_RAWKEY)
  1108.             {
  1109.                 if(MsgCode == HELP_CODE)
  1110.                     GuideDisplay(CONTEXT_TEXTBUFFER);
  1111.  
  1112.                 if(LastChar)
  1113.                 {
  1114.                     if((MsgCode & IECODE_UP_PREFIX) || !(LastQualifier & IEQUALIFIER_REPEAT))
  1115.                     {
  1116.                         SetGadgetAttrs(Scroller,BufferWindow,NULL,
  1117.                             PGA_Top,TopLine,
  1118.                         TAG_DONE);
  1119.  
  1120.                         UpdatePercent = TRUE;
  1121.                     }
  1122.                 }
  1123.  
  1124.                 if(LastChar = Char)
  1125.                 {
  1126.                         /* Use the numeric keypad keys to
  1127.                          * move through the buffer.
  1128.                          */
  1129.  
  1130.                     if(MsgQualifier & IEQUALIFIER_NUMERICPAD)
  1131.                     {
  1132.                             /* Remove the numpad qualifier. */
  1133.  
  1134.                         MsgQualifier &= ~IEQUALIFIER_NUMERICPAD;
  1135.  
  1136.                         switch(Char - '0')
  1137.                         {
  1138.                                 /* Jump to bottom. */
  1139.  
  1140.                             case 1: Char = CDN;
  1141.                                 MsgQualifier |= IEQUALIFIER_CONTROL;
  1142.                                 break;
  1143.  
  1144.                                 /* Jump to top. */
  1145.  
  1146.                             case 7: Char = CUP;
  1147.                                 MsgQualifier |= IEQUALIFIER_CONTROL;
  1148.                                 break;
  1149.  
  1150.                                 /* Move one page down. */
  1151.  
  1152.                             case 3: Char = CDN;
  1153.                                 MsgQualifier |= IEQUALIFIER_LSHIFT;
  1154.                                 break;
  1155.  
  1156.                                 /* Move one page up. */
  1157.  
  1158.                             case 9: Char = CUP;
  1159.                                 MsgQualifier |= IEQUALIFIER_LSHIFT;
  1160.                                 break;
  1161.  
  1162.                                 /* Move one line down. */
  1163.  
  1164.                             case 2: Char = CDN;
  1165.                                 break;
  1166.  
  1167.                                 /* Move one line up. */
  1168.  
  1169.                             case 8: Char = CUP;
  1170.                                 break;
  1171.                         }
  1172.                     }
  1173.  
  1174.                         /* Check cursor keys. */
  1175.  
  1176.                     switch(Char)
  1177.                     {
  1178.                             /* Scroll the buffer up. */
  1179.  
  1180.                         case CUP:
  1181.  
  1182.                             if(MsgQualifier & (IEQUALIFIER_CONTROL | IEQUALIFIER_LALT | IEQUALIFIER_RALT))
  1183.                             {
  1184.                                 MarkArea(-1,-1,-1);
  1185.  
  1186.                                 if(TopLine)
  1187.                                 {
  1188.                                     DisplayedLines = RedrawScreen(0);
  1189.  
  1190.                                     TopLine = 0;
  1191.                                     LastChar = 0;
  1192.  
  1193.                                     SetGadgetAttrs(Scroller,BufferWindow,NULL,
  1194.                                         PGA_Top,TopLine,
  1195.                                     TAG_DONE);
  1196.  
  1197.                                     UpdatePercent = TRUE;
  1198.                                 }
  1199.  
  1200.                                 break;
  1201.                             }
  1202.  
  1203.                             if(MsgQualifier & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT))
  1204.                             {
  1205.                                 LONG NewCurrentLine;
  1206.  
  1207.                                 if((NewCurrentLine = TopLine - NumBufferLines) < 0)
  1208.                                     NewCurrentLine = 0;
  1209.  
  1210.                                 MarkArea(-1,-1,-1);
  1211.  
  1212.                                 if(NewCurrentLine != TopLine)
  1213.                                 {
  1214.                                     DisplayedLines = RedrawScreen(NewCurrentLine);
  1215.  
  1216.                                     TopLine = NewCurrentLine;
  1217.  
  1218.                                     LastChar = 0;
  1219.  
  1220.                                     SetGadgetAttrs(Scroller,BufferWindow,NULL,
  1221.                                         PGA_Top,TopLine,
  1222.                                     TAG_DONE);
  1223.  
  1224.                                     UpdatePercent = TRUE;
  1225.                                 }
  1226.  
  1227.                                 break;
  1228.                             }
  1229.  
  1230.                             if(TopLine)
  1231.                             {
  1232.                                 MarkArea(-1,-1,-1);
  1233.  
  1234.                                 DisplayedLines = RedrawScreen(--TopLine);
  1235.  
  1236.                                 UpdatePercent = TRUE;
  1237.                             }
  1238.  
  1239.                             break;
  1240.  
  1241.                             /* Scroll the buffer down. */
  1242.  
  1243.                         case CDN:
  1244.  
  1245.                             if(MsgQualifier & (IEQUALIFIER_CONTROL | IEQUALIFIER_LALT | IEQUALIFIER_RALT))
  1246.                             {
  1247.                                 LONG NewCurrentLine;
  1248.  
  1249.                                 if((NewCurrentLine = Lines - NumBufferLines) < 0)
  1250.                                     NewCurrentLine = 0;
  1251.  
  1252.                                 MarkArea(-1,-1,-1);
  1253.  
  1254.                                 if(TopLine != NewCurrentLine)
  1255.                                 {
  1256.                                     DisplayedLines = RedrawScreen(NewCurrentLine);
  1257.  
  1258.                                     TopLine = NewCurrentLine;
  1259.  
  1260.                                     LastChar = 0;
  1261.  
  1262.                                     SetGadgetAttrs(Scroller,BufferWindow,NULL,
  1263.                                         PGA_Top,TopLine,
  1264.                                     TAG_DONE);
  1265.  
  1266.                                     UpdatePercent = TRUE;
  1267.                                 }
  1268.  
  1269.                                 break;
  1270.                             }
  1271.  
  1272.                             if(MsgQualifier & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT))
  1273.                             {
  1274.                                 LONG NewCurrentLine;
  1275.  
  1276.                                 if((NewCurrentLine = TopLine + (2 * NumBufferLines)) > Lines)
  1277.                                     NewCurrentLine = Lines;
  1278.  
  1279.                                 if((NewCurrentLine = NewCurrentLine - NumBufferLines) < 0)
  1280.                                     NewCurrentLine = 0;
  1281.  
  1282.                                 MarkArea(-1,-1,-1);
  1283.  
  1284.                                 if(NewCurrentLine != TopLine)
  1285.                                 {
  1286.                                     DisplayedLines = RedrawScreen(NewCurrentLine);
  1287.  
  1288.                                     TopLine = NewCurrentLine;
  1289.  
  1290.                                     LastChar = 0;
  1291.  
  1292.                                     SetGadgetAttrs(Scroller,BufferWindow,NULL,
  1293.                                         PGA_Top,TopLine,
  1294.                                     TAG_DONE);
  1295.  
  1296.                                     UpdatePercent = TRUE;
  1297.                                 }
  1298.  
  1299.                                 break;
  1300.                             }
  1301.  
  1302.                             if(TopLine + NumBufferLines < Lines)
  1303.                             {
  1304.                                 MarkArea(-1,-1,-1);
  1305.  
  1306.                                 DisplayedLines = RedrawScreen(TopLine + 1);
  1307.  
  1308.                                 TopLine++;
  1309.  
  1310.                                 UpdatePercent = TRUE;
  1311.                             }
  1312.  
  1313.                             break;
  1314.                     }
  1315.  
  1316.                     LastQualifier = MsgQualifier;
  1317.                 }
  1318.                 else
  1319.                     LastQualifier = NULL;
  1320.  
  1321.                 continue;
  1322.             }
  1323.  
  1324.                 /* User hit a mouse button. */
  1325.  
  1326.             if(MsgClass == IDCMP_MOUSEBUTTONS && (!ClickAndActivate || MsgCode != SELECTDOWN) && !(MsgCode & IECODE_UP_PREFIX))
  1327.             {
  1328.                 MarkArea(-1,-1,-1);
  1329.  
  1330.                     /* Reasonable dimensions? */
  1331.  
  1332.                 if(MouseY / LocalTextFontHeight < DisplayedLines && MouseX / LocalTextFontWidth < NumBufferColumns)
  1333.                 {
  1334.                     ObtainSemaphore(BufferSemaphore);
  1335.  
  1336.                     BufferClip();
  1337.  
  1338.                     UpdatePercent = TRUE;
  1339.  
  1340.                     LastTopLine = TopLine;
  1341.  
  1342.                     ReleaseSemaphore(BufferSemaphore);
  1343.  
  1344.                     if(MsgQualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT))
  1345.                     {
  1346.                         struct DataMsg Msg;
  1347.  
  1348.                         InitMsgItem(&Msg,BufferDestructor);
  1349.  
  1350.                         Msg . Type = DATAMSGTYPE_WRITECLIP;
  1351.                         Msg . Size = Config -> ClipConfig -> ClipboardUnit;
  1352.  
  1353.                         Forbid();
  1354.  
  1355.                         ClrSignal(1L << BufferSignal);
  1356.  
  1357.                         PutMsgItem(SpecialQueue,(struct MsgItem *)&Msg);
  1358.  
  1359.                         Wait(1L << BufferSignal);
  1360.  
  1361.                         Permit();
  1362.                     }
  1363.  
  1364.                     break;
  1365.                 }
  1366.             }
  1367.  
  1368.             if(MsgClass == IDCMP_MENUHELP)
  1369.                 GuideDisplay(CONTEXT_BUFFER_MENU);
  1370.  
  1371.             if(MsgClass == IDCMP_MENUPICK)
  1372.             {
  1373.                 struct MenuItem *MenuItem;
  1374.  
  1375.                 while(MsgCode != MENUNULL)
  1376.                 {
  1377.                     if(MenuItem = ItemAddress(BufferMenuStrip,MsgCode))
  1378.                     {
  1379.  
  1380.  
  1381.                         switch((ULONG)GTMENUITEM_USERDATA(MenuItem))
  1382.                         {
  1383.                             case MEN_SEARCH:
  1384.  
  1385.                                 if(Context)
  1386.                                     LT_ShowWindow(Context -> SearchHandle,TRUE);
  1387.                                 else
  1388.                                     Context = CreateSearchContext(BufferWindow,SearchBuffer,&HistoryHook,&SearchForward,&IgnoreCase,&WholeWords);
  1389.  
  1390.                                 UpdatePercent = TRUE;
  1391.  
  1392.                                 break;
  1393.  
  1394.                             case MEN_REPEAT:
  1395.  
  1396.                                 if(Context)
  1397.                                     LT_ShowWindow(Context -> SearchHandle,TRUE);
  1398.                                 else
  1399.                                 {
  1400.                                     if(SearchInfo)
  1401.                                         StartSearch(SearchInfo,SearchBuffer);
  1402.                                     else
  1403.                                         Context = CreateSearchContext(BufferWindow,SearchBuffer,&HistoryHook,&SearchForward,&IgnoreCase,&WholeWords);
  1404.                                 }
  1405.  
  1406.                                 UpdatePercent = TRUE;
  1407.  
  1408.                                 break;
  1409.  
  1410.                             case MEN_GOTO:
  1411.  
  1412.                                 if(Window)
  1413.                                     BumpWindow(Window);
  1414.  
  1415.                                 break;
  1416.  
  1417.                             case MEN_QUITBUF:
  1418.  
  1419.                                 BufferTerminated = TRUE;
  1420.                                 break;
  1421.  
  1422.                             case MEN_CLEARBUF_CONTENTS:
  1423.  
  1424.                                 if(Lines)
  1425.                                 {
  1426.                                     UpdatePercent = TRUE;
  1427.  
  1428.                                     LT_LockWindow(BufferWindow);
  1429.  
  1430.                                     if(MsgQualifier & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT))
  1431.                                     {
  1432.                                         FreeBuffer();
  1433.  
  1434.                                         LT_UnlockWindow(BufferWindow);
  1435.  
  1436.                                         FlushMsg(BufferWindow);
  1437.  
  1438.                                         DisplayedLines = RedrawScreen(TopLine = 0);
  1439.  
  1440.                                         SetGadgetAttrs(Scroller,BufferWindow,NULL,
  1441.                                             PGA_Top,    TopLine,
  1442.                                             PGA_Total,    Lines,
  1443.                                             PGA_Visible,    NumBufferLines,
  1444.                                         TAG_DONE);
  1445.  
  1446.                                         break;
  1447.                                     }
  1448.                                     else
  1449.                                     {
  1450.                                         if(Config -> MiscConfig -> ProtectiveMode)
  1451.                                         {
  1452.                                             if(!MyEasyRequest(BufferWindow,LocaleString(MSG_TERMBUFFER_BUFFER_STILL_HOLDS_LINES_TXT),LocaleString(MSG_GLOBAL_YES_NO_TXT),Lines))
  1453.                                             {
  1454.                                                 LT_UnlockWindow(BufferWindow);
  1455.  
  1456.                                                 break;
  1457.                                             }
  1458.                                         }
  1459.  
  1460.                                         FreeBuffer();
  1461.  
  1462.                                         LT_UnlockWindow(BufferWindow);
  1463.  
  1464.                                         FlushMsg(BufferWindow);
  1465.  
  1466.                                         DisplayedLines = RedrawScreen(TopLine = 0);
  1467.  
  1468.                                         SetGadgetAttrs(Scroller,BufferWindow,NULL,
  1469.                                             PGA_Top,    TopLine,
  1470.                                             PGA_Total,    Lines,
  1471.                                             PGA_Visible,    NumBufferLines,
  1472.                                         TAG_DONE);
  1473.  
  1474.                                         break;
  1475.                                     }
  1476.  
  1477.                                     LT_UnlockWindow(BufferWindow);
  1478.  
  1479.                                     FlushMsg(BufferWindow);
  1480.                                 }
  1481.  
  1482.                                 break;
  1483.                         }
  1484.  
  1485.                         MsgCode = MenuItem -> NextSelect;
  1486.                     }
  1487.                     else
  1488.                         break;
  1489.                 }
  1490.             }
  1491.  
  1492.         }
  1493.     }
  1494.     while(!BufferTerminated);
  1495.  
  1496.     if(Context)
  1497.         DeleteSearchContext(Context);
  1498.  
  1499.     if(SearchInfo)
  1500.         DeleteSearchInfo(SearchInfo);
  1501.  
  1502.     return(RingBack);
  1503. }
  1504.  
  1505.     /* BufferServer():
  1506.      *
  1507.      *    Asynchronous task to display the data stored in the
  1508.      *    scrollback display buffer.
  1509.      */
  1510.  
  1511. STATIC VOID __saveds
  1512. BufferServer(VOID)
  1513. {
  1514.     BOOLEAN             Defaults;
  1515.  
  1516.     struct ColorSpec     ColorSpec[3];
  1517.  
  1518.     LONG             Width,Height;
  1519.     ULONG             DisplayMode;
  1520.  
  1521.     struct Rectangle     DisplayClip;
  1522.     struct DimensionInfo     DimensionInfo;
  1523.  
  1524.     struct TextFont        *LocalFont;
  1525.  
  1526.     struct Task        *Father;
  1527.     BOOLEAN             RingBack = TRUE;
  1528.  
  1529.     Father = (struct Task *)SysBase -> ThisTask -> tc_UserData;
  1530.  
  1531.     memcpy(&LocalTextFont,&TextAttr,sizeof(struct TTextAttr));
  1532.  
  1533.     LocalTextFont . tta_Name    = LocalTextFontName;
  1534.     LocalTextFont . tta_YSize    = Config -> TerminalConfig -> TextFontHeight;
  1535.  
  1536.     strcpy(LocalTextFontName,Config -> TerminalConfig -> TextFontName);
  1537.  
  1538.     memcpy(&LocalUserFont,&UserFont,sizeof(struct TTextAttr));
  1539.  
  1540.     LocalUserFont . tta_Name = LocalUserFontName;
  1541.  
  1542.     strcpy(LocalUserFontName,UserFont . tta_Name);
  1543.  
  1544.     if(!Config -> CaptureConfig -> ConvertChars && Config -> TerminalConfig -> FontMode != FONT_STANDARD)
  1545.     {
  1546.         strcpy(LocalTextFontName,Config -> TerminalConfig -> IBMFontName);
  1547.  
  1548.         LocalTextFont . tta_YSize = Config -> TerminalConfig -> IBMFontHeight;
  1549.  
  1550.         NeedClipConversion = TRUE;
  1551.     }
  1552.     else
  1553.         NeedClipConversion = FALSE;
  1554.  
  1555.     if(LocalFont = OpenDiskFont(&LocalTextFont))
  1556.     {
  1557.         LocalTextFontBase    = LocalFont -> tf_Baseline;
  1558.         LocalTextFontWidth    = LocalFont -> tf_XSize;
  1559.         LocalTextFontHeight    = LocalTextFont . tta_YSize;
  1560.  
  1561.         CloseFont(LocalFont);
  1562.     }
  1563.  
  1564.         /* Reset top line index. */
  1565.  
  1566.     LastTopLine = -1;
  1567.  
  1568.         /* Up and running... */
  1569.  
  1570.     BufferTerminated = FALSE;
  1571.  
  1572.     Forbid();
  1573.  
  1574.     if(Window && DrawInfo)
  1575.     {
  1576.         UWORD Colour;
  1577.  
  1578.             /* Set up the startup colours for our buffer screen. */
  1579.  
  1580.         ColorSpec[0] . ColorIndex = 0;
  1581.         Colour = GetRGB4(Window -> WScreen -> ViewPort . ColorMap,DrawInfo -> dri_Pens[BACKGROUNDPEN]);
  1582.  
  1583.         ColorSpec[0] . Red        = (Colour >> 8) & 0xF;
  1584.         ColorSpec[0] . Green        = (Colour >> 4) & 0xF;
  1585.         ColorSpec[0] . Blue        = (Colour     ) & 0xF;
  1586.  
  1587.         ColorSpec[1] . ColorIndex = 1;
  1588.         Colour = GetRGB4(Window -> WScreen -> ViewPort . ColorMap,DrawInfo -> dri_Pens[TEXTPEN]);
  1589.  
  1590.         ColorSpec[1] . Red        = (Colour >> 8) & 0xF;
  1591.         ColorSpec[1] . Green        = (Colour >> 4) & 0xF;
  1592.         ColorSpec[1] . Blue        = (Colour     ) & 0xF;
  1593.  
  1594.         ColorSpec[2] . ColorIndex = -1;
  1595.  
  1596.         Defaults = FALSE;
  1597.     }
  1598.     else
  1599.         Defaults = TRUE;
  1600.  
  1601.     Permit();
  1602.  
  1603.         /* We'll use a fixed screen width, only the
  1604.          * height is adapted from the main screen.
  1605.          */
  1606.  
  1607.     DisplayMode = Config -> CaptureConfig -> BufferScreenMode;
  1608.  
  1609.     if(ModeNotAvailable(DisplayMode))
  1610.         DisplayMode = Config -> ScreenConfig -> DisplayMode;
  1611.  
  1612.     if(ModeNotAvailable(DisplayMode))
  1613.     {
  1614.         struct Screen *PubScreen = LockPubScreen(NULL);
  1615.  
  1616.         if(PubScreen)
  1617.         {
  1618.             DisplayMode = GetVPModeID(&PubScreen -> ViewPort);
  1619.  
  1620.             UnlockPubScreen(NULL,PubScreen);
  1621.         }
  1622.         else
  1623.             DisplayMode = DEFAULT_MONITOR_ID | HIRES_KEY;
  1624.     }
  1625.  
  1626.         /* Set up the actual width of the screen we want. */
  1627.  
  1628.     Width = Config -> CaptureConfig -> BufferWidth * LocalTextFontWidth + ArrowWidth + 1;
  1629.  
  1630.     if((BufferSignal = AllocSignal(-1)) != -1)
  1631.     {
  1632.             /* Get the mode dimension info. */
  1633.  
  1634.         if(GetDisplayInfoData(NULL,(APTR)&DimensionInfo,sizeof(struct DimensionInfo),DTAG_DIMS,DisplayMode))
  1635.         {
  1636.                 /* Determine maximum text overscan width. */
  1637.  
  1638.             LONG TextWidth = DimensionInfo . TxtOScan . MaxX - DimensionInfo . TxtOScan . MinX + 1;
  1639.  
  1640.                 /* Too small? */
  1641.  
  1642.             if(Width < DimensionInfo . MinRasterWidth)
  1643.                 Width = DimensionInfo . MinRasterWidth;
  1644.  
  1645.                 /* Far too large? */
  1646.  
  1647.             if(Width > DimensionInfo . MaxRasterWidth)
  1648.                 Width = DimensionInfo . MaxRasterWidth;
  1649.  
  1650.                 /* A bit too large? */
  1651.  
  1652.             if(Width > TextWidth)
  1653.                 Width = TextWidth;
  1654.  
  1655.             if(LocalFont = OpenDiskFont(&LocalTextFont))
  1656.             {
  1657.                     /* Inquire the text overscan dimensions. */
  1658.  
  1659.                 if(QueryOverscan(DisplayMode,&DisplayClip,OSCAN_TEXT))
  1660.                 {
  1661.                         /* Centre the buffer screen. */
  1662.  
  1663.                     if(DisplayClip . MaxX - DisplayClip . MinX + 1 > Width)
  1664.                     {
  1665.                         LONG Differ = (DisplayClip . MaxX - DisplayClip . MinX + 1 - Width) / 2;
  1666.  
  1667.                         switch(Config -> CaptureConfig -> BufferScreenPosition)
  1668.                         {
  1669.                             case SCREEN_LEFT:
  1670.  
  1671.                                 DisplayClip . MaxX = DisplayClip . MinX + Width;
  1672.                                 break;
  1673.  
  1674.                             case SCREEN_RIGHT:
  1675.  
  1676.                                 DisplayClip . MinX = DisplayClip . MaxX - Width;
  1677.                                 break;
  1678.  
  1679.                             case SCREEN_CENTRE:
  1680.  
  1681.                                 DisplayClip . MinX += Differ;
  1682.                                 DisplayClip . MaxX -= Differ;
  1683.  
  1684.                                 break;
  1685.                         }
  1686.                     }
  1687.  
  1688.                         /* Open a single bitplane clone of the main screen. */
  1689.  
  1690.                     if(BufferScreen = (struct Screen *)OpenScreenTags(NULL,
  1691.                         SA_Title,    LocaleString(MSG_TERMBUFFER_TERM_BUFFER_TXT),
  1692.                         SA_Depth,    1,
  1693.                         SA_Left,    DisplayClip . MinX,
  1694.                         SA_DClip,    &DisplayClip,
  1695.                         SA_DisplayID,    DisplayMode,
  1696.                         SA_Font,    &LocalUserFont,
  1697.                         SA_Behind,    TRUE,
  1698.                         SA_AutoScroll,    TRUE,
  1699.  
  1700.                         Defaults ? TAG_IGNORE : SA_Colors,ColorSpec,
  1701.                     TAG_END))
  1702.                     {
  1703.                         if(BufferVisualInfo = GetVisualInfo(BufferScreen,TAG_DONE))
  1704.                         {
  1705.                             LocalizeMenu(BufferMenu,MSG_TERMBUFFER_PROJECT_MEN);
  1706.  
  1707.                             if(BufferMenuStrip = CreateMenus(BufferMenu,TAG_DONE))
  1708.                             {
  1709.                                 if(BufferDrawInfo = GetScreenDrawInfo(BufferScreen))
  1710.                                 {
  1711.                                     if(!CreateMenuGlyphs(BufferScreen,BufferDrawInfo,&BufferAmigaGlyph,&BufferCheckGlyph))
  1712.                                     {
  1713.                                         FreeScreenDrawInfo(BufferScreen,BufferDrawInfo);
  1714.  
  1715.                                         BufferDrawInfo = NULL;
  1716.                                     }
  1717.                                 }
  1718.  
  1719.                                 if(LayoutMenus(BufferMenuStrip,BufferVisualInfo,
  1720.                                     BufferAmigaGlyph ? GTMN_AmigaKey :  TAG_IGNORE, BufferAmigaGlyph,
  1721.                                     BufferCheckGlyph ? GTMN_Checkmark : TAG_IGNORE, BufferCheckGlyph,
  1722.  
  1723.                                     GTMN_TextAttr,        &LocalUserFont,
  1724.                                     GTMN_NewLookMenus,    TRUE,
  1725.                                 TAG_DONE))
  1726.                                 {
  1727.                                     Height = (BufferScreen -> Height - (BufferScreen -> BarHeight + 2)) / LocalTextFontHeight;
  1728.  
  1729.                                         /* Open a cute window on our buffer screen. */
  1730.  
  1731.                                     if(BufferWindow = OpenWindowTags(NULL,
  1732.                                         WA_Top,        BufferScreen -> BarHeight + 2,
  1733.                                         WA_Left,    0,
  1734.                                         WA_Width,    BufferScreen -> Width,
  1735.                                         WA_Height,    Height * LocalTextFontHeight,
  1736.                                         WA_Backdrop,    TRUE,
  1737.                                         WA_Borderless,    TRUE,
  1738.                                         WA_SmartRefresh,FALSE,
  1739.                                         WA_CustomScreen,BufferScreen,
  1740.                                         WA_RMBTrap,    TRUE,
  1741.                                         WA_NewLookMenus,TRUE,
  1742.                                         WA_RptQueue,    1,
  1743.                                         WA_IDCMP,    IDCMP_IDCMPUPDATE | IDCMP_RAWKEY | IDCMP_INACTIVEWINDOW | IDCMP_ACTIVEWINDOW | IDCMP_MOUSEBUTTONS | IDCMP_MENUPICK | IDCMP_GADGETUP | IDCMP_GADGETDOWN | IDCMP_MOUSEMOVE | IDCMP_MENUHELP,
  1744.                                         WA_MenuHelp,    TRUE,
  1745.  
  1746.                                         BufferAmigaGlyph ? WA_AmigaKey  : TAG_IGNORE, BufferAmigaGlyph,
  1747.                                         BufferCheckGlyph ? WA_Checkmark : TAG_IGNORE, BufferCheckGlyph,
  1748.                                     TAG_DONE))
  1749.                                     {
  1750.                                         if(BufferLineWidths = (UWORD *)AllocVecPooled(2 * sizeof(UWORD) * (BufferWindow -> Height / LocalTextFontHeight + 1) + sizeof(UWORD) * (BufferWindow -> Width / LocalTextFontWidth + 1),MEMF_ANY | MEMF_CLEAR))
  1751.                                         {
  1752.                                             UWORD    Index;
  1753.                                             WORD    i;
  1754.  
  1755.                                             BufferLineOffsets    = &BufferLineWidths[BufferWindow -> Height / LocalTextFontHeight + 1];
  1756.                                             BufferColumnOffsets    = &BufferLineOffsets[BufferWindow -> Height / LocalTextFontHeight + 1];
  1757.  
  1758.                                             for(i = Index = 0 ; i < BufferWindow -> Height / LocalTextFontHeight + 1 ; i++)
  1759.                                             {
  1760.                                                 BufferLineOffsets[i] = Index;
  1761.  
  1762.                                                 Index += LocalTextFontHeight;
  1763.                                             }
  1764.  
  1765.                                             for(i = Index = 0 ; i < BufferWindow -> Width / LocalTextFontWidth + 1 ; i++)
  1766.                                             {
  1767.                                                 BufferColumnOffsets[i] = Index;
  1768.  
  1769.                                                 Index += LocalTextFontWidth;
  1770.                                             }
  1771.  
  1772.                                             if(CreateScroller(BufferWindow -> Height))
  1773.                                             {
  1774.                                                 ObtainSemaphore(&BufferTaskSemaphore);
  1775.  
  1776.                                                 BufferTask = SysBase -> ThisTask;
  1777.  
  1778.                                                 ReleaseSemaphore(&BufferTaskSemaphore);
  1779.  
  1780.                                                     /* Signal our father process that
  1781.                                                      * we're running.
  1782.                                                      */
  1783.  
  1784.                                                 Signal(Father,SIG_HANDSHAKE);
  1785.  
  1786.                                                 Father = NULL;
  1787.  
  1788.                                                 SetMenuStrip(BufferWindow,BufferMenuStrip);
  1789.  
  1790.                                                 AddGList(BufferWindow,Scroller,(UWORD)-1,(UWORD)-1,NULL);
  1791.                                                 RefreshGList(Scroller,BufferWindow,NULL,(UWORD)-1);
  1792.  
  1793.                                                     /* Determine maximum dimensions of
  1794.                                                      * the buffer screen (in rows and
  1795.                                                      * columns).
  1796.                                                      */
  1797.  
  1798.                                                 NumBufferColumns    = (BufferWindow -> Width - (ArrowWidth + 1)) / LocalTextFontWidth;
  1799.                                                 NumBufferLines        = BufferWindow -> Height / LocalTextFontHeight;
  1800.  
  1801.                                                 if(TopLine == -1 || !Config -> CaptureConfig -> RememberBufferScreen)
  1802.                                                 {
  1803.                                                     switch(Config -> CaptureConfig -> OpenBufferScreen)
  1804.                                                     {
  1805.                                                         case BUFFER_TOP:
  1806.  
  1807.                                                             TopLine = 0;
  1808.                                                             break;
  1809.  
  1810.                                                         case BUFFER_END:
  1811.  
  1812.                                                             if((TopLine = Lines - NumBufferLines) < 0)
  1813.                                                                 TopLine = 0;
  1814.  
  1815.                                                             break;
  1816.  
  1817.                                                         default:
  1818.  
  1819.                                                             TopLine = 0;
  1820.                                                             break;
  1821.                                                     }
  1822.                                                 }
  1823.  
  1824.                                                 if(TopLine > Lines - NumBufferLines)
  1825.                                                     TopLine = 0;
  1826.  
  1827.                                                 BPort = BufferWindow -> RPort;
  1828.  
  1829.                                                 SetFont(BPort,LocalFont);
  1830.  
  1831.                                                     /* Bring the screen to the front. */
  1832.  
  1833.                                                 BumpWindow(BufferWindow);
  1834.  
  1835.                                                     /* Set the drawing pens for the window. */
  1836.  
  1837.                                                 SetAPen(BPort,1);
  1838.                                                 SetBPen(BPort,0);
  1839.                                                 SetDrMd(BPort,JAM2);
  1840.  
  1841.                                                     /* Initial creation of the buffer display. */
  1842.  
  1843.                                                 DisplayedLines = RedrawScreen(TopLine);
  1844.  
  1845.                                                 SetGadgetAttrs(Scroller,BufferWindow,NULL,
  1846.                                                     PGA_Top,    TopLine,
  1847.                                                     PGA_Total,    Lines,
  1848.                                                     PGA_Visible,    NumBufferLines,
  1849.                                                 TAG_DONE);
  1850.  
  1851.                                                 BufferWindow -> Flags &= ~WFLG_RMBTRAP;
  1852.  
  1853.                                                 RingBack = HandleBuffer(TextLength(BufferScreen -> BarLayer -> rp,LocaleString(MSG_TERMBUFFER_TERM_BUFFER_TXT),strlen(LocaleString(MSG_TERMBUFFER_TERM_BUFFER_TXT))) + TextLength(BufferScreen -> BarLayer -> rp," ",1) + 4);
  1854.  
  1855.                                                 RemoveGList(BufferWindow,Scroller,(UWORD)-1);
  1856.  
  1857.                                                 DeleteScroller();
  1858.                                             }
  1859.  
  1860.                                             FreeVecPooled(BufferLineWidths);
  1861.                                         }
  1862.  
  1863.                                         if(Window)
  1864.                                             BumpWindow(Window);
  1865.  
  1866.                                         MarkArea(-1,-1,-1);
  1867.  
  1868.                                         ScreenToBack(BufferScreen);
  1869.  
  1870.                                         BufferWindow -> Flags |= WFLG_RMBTRAP;
  1871.  
  1872.                                         ClearMenuStrip(BufferWindow);
  1873.  
  1874.                                         LT_DeleteWindowLock(BufferWindow);
  1875.  
  1876.                                         CloseWindow(BufferWindow);
  1877.                                     }
  1878.                                 }
  1879.  
  1880.                                 DisposeObject(BufferAmigaGlyph);
  1881.                                 DisposeObject(BufferCheckGlyph);
  1882.  
  1883.                                 FreeScreenDrawInfo(BufferScreen,BufferDrawInfo);
  1884.  
  1885.                                 FreeMenus(BufferMenuStrip);
  1886.                             }
  1887.  
  1888.                             FreeVisualInfo(BufferVisualInfo);
  1889.                         }
  1890.  
  1891.                         CloseScreen(BufferScreen);
  1892.                     }
  1893.                 }
  1894.  
  1895.                 CloseFont(LocalFont);
  1896.             }
  1897.         }
  1898.  
  1899.         FreeSignal(BufferSignal);
  1900.     }
  1901.  
  1902.     ObtainSemaphore(&BufferTaskSemaphore);
  1903.  
  1904.     BufferTask = NULL;
  1905.  
  1906.     ReleaseSemaphore(&BufferTaskSemaphore);
  1907.  
  1908.     Forbid();
  1909.  
  1910.     if(RingBack)
  1911.     {
  1912.         if(Father)
  1913.             Signal(Father,SIG_HANDSHAKE);
  1914.         else
  1915.             Signal(ThisProcess,SIG_HANDSHAKE);
  1916.     }
  1917. }
  1918.  
  1919.     /* LaunchBuffer():
  1920.      *
  1921.      *    Launch the buffer process.
  1922.      */
  1923.  
  1924. BYTE
  1925. LaunchBuffer()
  1926. {
  1927.     ObtainSemaphore(&BufferTaskSemaphore);
  1928.  
  1929.         /* Is the buffer process already running? */
  1930.  
  1931.     if(BufferTask)
  1932.     {
  1933.             /* Tell it to bring its screen to the front. */
  1934.  
  1935.         Signal(BufferTask,SIG_TOFRONT);
  1936.  
  1937.         ReleaseSemaphore(&BufferTaskSemaphore);
  1938.  
  1939.             /* Return success. */
  1940.  
  1941.         return(TRUE);
  1942.     }
  1943.     else
  1944.     {
  1945.         struct Task    *Child;
  1946.         BYTE         Result = FALSE;
  1947.  
  1948.         ReleaseSemaphore(&BufferTaskSemaphore);
  1949.  
  1950.         Forbid();
  1951.  
  1952.             /* Launch the buffer process. */
  1953.  
  1954.         if(Child = (struct Task *)CreateNewProcTags(
  1955.             NP_Entry,    BufferServer,
  1956.             NP_Name,    "term Buffer Process",
  1957.             NP_Priority,    SysBase -> ThisTask -> tc_Node . ln_Pri,
  1958.             NP_StackSize,    4000,
  1959.             NP_WindowPtr,    -1,
  1960.         TAG_END))
  1961.         {
  1962.             Child -> tc_UserData = SysBase -> ThisTask;
  1963.  
  1964.             ClrSignal(SIG_HANDSHAKE);
  1965.  
  1966.             Wait(SIG_HANDSHAKE);
  1967.  
  1968.             ObtainSemaphore(&BufferTaskSemaphore);
  1969.  
  1970.             if(BufferTask)
  1971.                 Result = TRUE;
  1972.  
  1973.             ReleaseSemaphore(&BufferTaskSemaphore);
  1974.         }
  1975.  
  1976.         Permit();
  1977.  
  1978.             /* Return the result. */
  1979.  
  1980.         return(Result);
  1981.     }
  1982. }
  1983.  
  1984.     /* TerminateBuffer():
  1985.      *
  1986.      *    Terminate the buffer process.
  1987.      */
  1988.  
  1989. VOID
  1990. TerminateBuffer()
  1991. {
  1992.     ObtainSemaphore(&BufferTaskSemaphore);
  1993.  
  1994.     if(BufferTask)
  1995.     {
  1996.         Forbid();
  1997.  
  1998.         Signal(BufferTask,SIG_KILL);
  1999.  
  2000.         ReleaseSemaphore(&BufferTaskSemaphore);
  2001.  
  2002.         ClrSignal(SIG_HANDSHAKE);
  2003.  
  2004.         Wait(SIG_HANDSHAKE);
  2005.  
  2006.         Permit();
  2007.     }
  2008.     else
  2009.         ReleaseSemaphore(&BufferTaskSemaphore);
  2010.  
  2011.     LastTopLine = -1;
  2012. }
  2013.